/**
 * Copyright (c) 2012-2016, www.tinygroup.org (luo_guo@icloud.com).
 * <p>
 * Licensed under the GPL, Version 3.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.gnu.org/licenses/gpl.html
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.tinygroup.template.fileresolver;

import org.tinygroup.commons.tools.StringUtil;
import org.tinygroup.config.util.ConfigurationUtil;
import org.tinygroup.fileresolver.impl.AbstractFileProcessor;
import org.tinygroup.logger.LogLevel;
import org.tinygroup.template.ResourceLoader;
import org.tinygroup.template.Template;
import org.tinygroup.template.TemplateEngine;
import org.tinygroup.template.impl.TemplateEngineDefault;
import org.tinygroup.template.loader.FileObjectResourceLoader;
import org.tinygroup.template.loader.FileResourceManager;
import org.tinygroup.template.loader.TemplateLoadUtil;
import org.tinygroup.vfs.FileObject;
import org.tinygroup.xmlparser.node.XmlNode;

/**
 * tiny宏文件扫描
 *
 * @author renhui
 */
public class TinyMacroFileProcessor extends AbstractFileProcessor {

    private static final String TINY_TEMPLATE_CONFIG = "/application/template-config";
    private static final String TINY_TEMPLATE_CONFIG_PATH = "/templateconfig.config.xml";
    //配置的三个参数名
    private static final String TEMPLATE_EXT_FILE_NAME = "templateExtFileName";
    private static final String LAYOUT_EXT_FILE_NAME = "layoutExtFileName";
    private static final String COMPONENT_EXT_FILE_NAME = "componentExtFileName";
    
    //配置参数的默认值
    private static final String TEMPLATE_EXT_DEFALUT = "page";
    private static final String LAYOUT_EXT_DEFALUT = "layout";
    private static final String COMPONENT_EXT_DEFALUT = "component";
    
    private String templateExtFileName ;
    private String layoutExtFileName ;
    private String componentExtFileName ;
    
    private boolean initTag = false;
    private TemplateEngine engine;
    private FileResourceManager fileResourceManager;

    public TemplateEngine getEngine() {
        return engine;
    }

    public void setEngine(TemplateEngine engine) {
        this.engine = engine;
    }

    public FileResourceManager getFileResourceManager() {
		return fileResourceManager;
	}

	public void setFileResourceManager(FileResourceManager fileResourceManager) {
		this.fileResourceManager = fileResourceManager;
	}

	public boolean checkMatch(FileObject fileObject) {
		init();
        return  isPage(fileObject.getFileName()) || isLayout(fileObject.getFileName()) || isComponent(fileObject.getFileName());
    }
    
    private boolean isPage(String fileName){
    	return fileName.endsWith("."+templateExtFileName);
    }
    
    private boolean isLayout(String fileName){
    	return fileName.endsWith("."+layoutExtFileName);
    }
    
    private boolean isComponent(String fileName){
    	return fileName.endsWith("."+componentExtFileName);
    }
    
    /**
     * 解析XML配置，获得动态的页面文件/布局文件/宏文件后缀(时间点必须在checkMatch之前)
     */
    private  void init(){
       if(!initTag){
    	   reloadTemplateConfig();
    	   initTag = true;
       }
    }

    public void process() {
    	
    	for (FileObject fileObject : deleteList) {
    		LOGGER.logMessage(LogLevel.INFO, "模板资源文件[{0}]开始移除",fileObject.getAbsolutePath());
    		try {
    			fileResourceManager.removeResource(fileObject.getPath());
    			engine.removeTemplate(fileObject.getPath());
            } catch (Exception e) {
                LOGGER.errorMessage("移除模板资源文件[{0}]出错,卸载主键[{1}]", e,fileObject.getAbsolutePath(),fileObject.getPath());
                continue;
            }
    		LOGGER.logMessage(LogLevel.INFO, "模板资源文件[{0}]移除完毕,卸载主键[{1}]",fileObject.getAbsolutePath(),fileObject.getPath());
    	}
    	
        for (FileObject fileObject : changeList) {
            LOGGER.logMessage(LogLevel.INFO, "模板资源文件[{0}]开始加载",fileObject.getAbsolutePath());
            try {
            	fileResourceManager.addResource(fileObject.getPath(), fileObject);
            	Template template = TemplateLoadUtil.loadComponent((TemplateEngineDefault)engine,fileObject);
            	template.setTemplateEngine(engine);
            	engine.getRepositories().put(fileObject.getPath(), template);
            	if(isComponent(fileObject.getFileName())){
            		engine.registerMacroLibrary(template);
            	}
            } catch (Exception e) {
                LOGGER.errorMessage("加载模板资源文件[{0}]出错,注册主键[{1}]", e,fileObject.getAbsolutePath(),fileObject.getPath());
                continue;
            }
            LOGGER.logMessage(LogLevel.INFO, "模板资源文件[{0}]加载完毕,注册主键[{1}]",fileObject.getAbsolutePath(),fileObject.getPath());
        }
    }

    /**
     * 设置模板引擎TemplateEngine
     */
    private synchronized void reloadTemplateConfig() {
        //合并节点
        XmlNode totalConfig = ConfigurationUtil.combineXmlNode(applicationConfig, componentConfig);

        templateExtFileName = TEMPLATE_EXT_DEFALUT;
        layoutExtFileName = LAYOUT_EXT_DEFALUT;
        componentExtFileName = COMPONENT_EXT_DEFALUT;

        if (totalConfig != null) {
            templateExtFileName = StringUtil.defaultIfBlank(totalConfig.getAttribute(TEMPLATE_EXT_FILE_NAME), TEMPLATE_EXT_DEFALUT);
            layoutExtFileName = StringUtil.defaultIfBlank(totalConfig.getAttribute(LAYOUT_EXT_FILE_NAME), LAYOUT_EXT_DEFALUT);
            componentExtFileName = StringUtil.defaultIfBlank(totalConfig.getAttribute(COMPONENT_EXT_FILE_NAME), COMPONENT_EXT_DEFALUT);
        }

        boolean addTag = true;
        for(ResourceLoader loader:engine.getResourceLoaderList()){
        	if(loader instanceof FileObjectResourceLoader){
        		addTag = false;
        		break;
        	}
        }
        fileResourceManager.setFileResolver(fileResolver);
        //执行动态注册逻辑
        if(addTag){
           FileObjectResourceLoader fileObjectResourceLoader = new FileObjectResourceLoader(templateExtFileName,layoutExtFileName,componentExtFileName);
           fileObjectResourceLoader.setFileResourceManager(fileResourceManager);
           engine.addResourceLoader(fileObjectResourceLoader);
        }
    }

    public void config(XmlNode applicationConfig, XmlNode componentConfig) {
        super.config(applicationConfig, componentConfig);
    }

    public String getComponentConfigPath() {
        return TINY_TEMPLATE_CONFIG_PATH;
    }

    public String getApplicationNodePath() {
        return TINY_TEMPLATE_CONFIG;
    }

}
